#include "ray.h"
#include <math.h>
#include <iostream>
#include "Sphere.h"
#include "float.h"
#include "HitableList.h"
#include "Camera.h"
#include "Random.h"
#include "Lambertian.h"
#include "Metal.h"
#include "Dielectrics.h"

class Chapter10
{
public:
	void Render() {
		using namespace std;
		//打开输出文件
		std::ofstream outf("G:\\Chapter10.ppm");
		//获取cout默认输出
		streambuf *default_buf = cout.rdbuf();
		//重定向cout输出到文件
		std::cout.rdbuf(outf.rdbuf());

		int nx = 200;
		int ny = 100;
		int ns = 100;
		std::cout << "P3\n" << nx << " " << ny << "\n255\n";
		Camera cam;
		Hitable *list[5];
		list[0] = new Sphere(Vector3(0, 0, -1), 0.5, new Lambertain(Vector3(0.8, 0.3, 0.3)));
		list[1] = new Sphere(Vector3(0, -100.5, -1), 100, new Lambertain(Vector3(0.8, 0.8, 0)));
		list[2] = new Sphere(Vector3(1, 0, -1), 0.5, new Metal(Vector3(0, 0, 1.0), 1));
		list[3] = new Sphere(Vector3(-1, 0, -1), 0.5, new Dielectrics(1.5));
		list[4] = new Sphere(Vector3(-1, 0, -1), -0.45, new Dielectrics(1.5));

		Hitable *world = new HitableList(list, 5);
		for (int j = ny - 1; j >= 0; j--)
		{
			for (int i = 0; i < nx; i++)
			{
				Vector3 col = Vector3(0, 0, 0);
				for (int s = 0; s < ns; s++)
				{
					float u = float(i + random_double()) / float(nx);
					float v = float(j + random_double()) / float(ny);
					Ray r = cam.get_ray(u, v);
					col += Color(r, world, 1);
				}
				col /= ns;
				col = Vector3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));

				int ir = int(255.99 * col.r());
				int ig = int(255.99 * col.g());
				int ib = int(255.99 * col.b());

				std::cout << ir << " " << ig << " " << ib << "\n";
			}
		}


		//恢复cout默认输出
		cout.rdbuf(default_buf);
	}

private:
	Vector3 Color(const Ray&r, Hitable *world, int depth) {
		HitRecord rec;
		if (world->hit(r, 0.0001, FLT_MAX, rec)) {
			Ray scattered;
			Vector3 attenuation;
			if (depth < 50 && rec.pMaterial->scatter(r, rec, attenuation, scattered))
			{
				return attenuation * Color(scattered, world, depth + 1);
			}
			else
			{
				return Vector3(0, 0, 0);
			}
		}
		else {
			Vector3 unit_vector(r.direction());
			float t = 0.5*(unit_vector.y() + 1.0);
			return (1 - t)*Vector3(1, 1, 1) + t * Vector3(0.5, 0.7, 1.0);
		}
	}
};
